package cn.demoncat.util.redis.config;

import cn.demoncat.util.lang.entity.ListStr;
import cn.demoncat.util.redis.entity.RedisCache;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.spring.cache.CacheConfig;
import org.redisson.spring.cache.RedissonSpringCacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Redis配置
 *
 * @author 延晓磊
 * @since 2021年02月10日
 */
@EnableCaching
@Configuration
public class RedisConfig {

    @Autowired
    private RedisProperties redisProperties;

    /**
     * Spring Cache缓存列表
     *
     * 1、服务中创建 RedisCache，添加到RedisConfig.CACHES
     * 2、方法添加注解：@Cacheable 方法执行后将返回值添加到缓存，下次查询时直接查缓存；@CacheEvict 方法执行后删除缓存
     */
    public static final List<RedisCache> CACHES = new ArrayList<>();

    /**
     * Redisson Client
     *
     * Redisson是Redis的封装，提供了分布式的Lock锁和集合对象。
     *
     * @return
     *
     * @see <a href="https://github.com/redisson/redisson/wiki">文档</a>
     * @see <a href="https://github.com/redisson/redisson">源码</a>
     */
    @Bean(destroyMethod="shutdown")
    public RedissonClient redissonClient() {
        Config config = new Config();
        if (StringUtils.isNotBlank(redisProperties.getUrl())) {
            // 单机：redis://ip:port
            config.useSingleServer().setAddress(redisProperties.getUrl());
        }else{
            // 集群：[ip:port]
            config.useClusterServers().addNodeAddress(ListStr.toArr(redisProperties.getCluster().getNodes()));
        }
        // 创建客户端
        return Redisson.create(config);
    }

    /**
     * Spring Cache
     *
     * 1、启用 @EnableCaching
     * 2、根据CACHES配置 CacheManager
     *
     * @param redissonClient
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedissonClient redissonClient) {
        // 缓存配置
        Map<String, CacheConfig> config = new HashMap<>();
        for (RedisCache cache : CACHES) {
            config.put(cache.getName(), new CacheConfig(cache.getTtl() * 1000, cache.getMaxIdleTime() * 1000));
        }
        // 缓存管理器
        return new RedissonSpringCacheManager(redissonClient, config);
    }

}
